home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume91 / utilitys / ed3_1_1 / part04 / sysgr.c
C/C++ Source or Header  |  1991-11-07  |  25KB  |  1,068 lines

  1. /*
  2.     Graphic initialization/cleanup for the 3D editor, ED3
  3.     Amiga-specific
  4.  
  5. 10-18-91 added minimal memory-management for menus and gadgets
  6. 10-13-91 rem ShowGetLong and ShowThreeGadText
  7.          added native Intuition window/gadget drivers
  8. 09-02-91 check if the mouse hasn't moved far, in addition to DoubleClick
  9. 08-28-91 added Cut, Copy etc. menu items
  10. 08-24-91 ability to specify gadgets as non-selectable
  11. 08-23-91 now uses the system default font for gadgets, even on workbench
  12.          moved Save, Quit etc. from gadgets to menus
  13.          added toggle_menuitem()
  14. 08-10-91 added dynamic menu functions
  15. 08-08-91 changed clipping method
  16. 02-26-91 removed arp file requestor code
  17.          added reqlib code
  18. */
  19.  
  20. #include <intuition/intuition.h> /* includes clip, layers, rastport->gfx, view */
  21. #include <exec/lists.h>
  22. #include <exec/memory.h>
  23. #include <graphics/gfxmacros.h>
  24. #include <graphics/regions.h>
  25.  
  26. #include <exec/libraries.h>
  27. #include <libraries/dosextens.h>/* For the process structure definition. */
  28. #include <libraries/dos.h>    /* we use a FileInfoBlock */
  29. #include <libraries/reqbase.h>
  30.  
  31. #ifdef LATTICE
  32. #include <proto/intuition.h>
  33. #include <proto/graphics.h>
  34. #else
  35. #include <functions.h>
  36. struct GfxBase *GfxBase = 0L;
  37. struct IntuitionBase *IntuitionBase = 0L;
  38. #endif
  39. struct ReqLib *ReqBase = 0L;
  40.  
  41. #include <stdio.h>
  42. #include "ed3.h"    /* funtion defs, #defines, typedefs */
  43.  
  44. #define MAXPATH    ( (FCHARS * 10) + DSIZE + 1)    /* Size of a pathname */
  45. #define K_shift    0x60
  46. #define MAX_REMEMBERS    500
  47.  
  48. struct Process    *myprocess = NULL;
  49. APTR olderrorwindow;
  50.  
  51. struct FileRequester    MyFileReqStruct;
  52. char filename[FCHARS];
  53. char directoryname[DSIZE];
  54. char answerarray[DSIZE+FCHARS];
  55.  
  56. struct Screen *screen = NULL;
  57. struct Window *window = NULL, *window2 = NULL;
  58. struct RastPort *rp = NULL,    /* RastPort of main editing window */
  59.         *screen_rport,        /* RastPort of underlying screen */
  60.         *rp2 = NULL;        /* RastPort of the small communication window */
  61. struct ViewPort *vp = NULL;
  62. struct Layer *my_layer;
  63. struct TextAttr default_ta[1];
  64. int active_text;    /* id of the active text gadget; 0 if none */
  65. int win2_mempoint;
  66.  
  67. typedef struct
  68. {
  69.     long bytes;
  70.     void *memory;
  71. } Remember;
  72.  
  73. Remember remember_mem[MAX_REMEMBERS];
  74. int members = 0;
  75.  
  76. #define PALETTES 10
  77. #define MAX_GADGETS 50
  78.  
  79. UWORD palette[PALETTES][4] =
  80. {
  81.  { 0x999, 0x000, 0xfff, 0xff0 },
  82.  { 0xa98, 0x310, 0xfed, 0xfa0 },
  83.  { 0xa88, 0x311, 0xfdd, 0xf66 },
  84.  { 0x8a8, 0x020, 0xdfd, 0x0e0 },
  85.  { 0x6a9, 0x021, 0xbfd, 0x0f7 },
  86.  { 0x599, 0x021, 0xbfe, 0x0fe },
  87.  { 0x69a, 0x012, 0xbef, 0x0cf },
  88.  { 0x68a, 0x012, 0xcdf, 0x07f },
  89.  { 0xa8a, 0x202, 0xfef, 0xfaf },
  90.  { 0xb97, 0x321, 0xfed, 0x0f0 },
  91. };
  92.  
  93. UWORD mypens[] =
  94. {
  95.   0,    /* detail */
  96.   1,    /* block */
  97.   1,    /* text */
  98.   2,    /* shine */
  99.   1,    /* shadow */
  100.   3,    /* hifill */
  101.   1,    /* hifilltext */
  102.   0,    /* background */
  103.   3,    /* hilighttext */
  104.   ~0,    /* TERMINATOR! */
  105. };
  106.  
  107. struct TagItem mytags[2];
  108.  
  109. struct ExtNewScreen NS =
  110. {
  111.     0,0,0,STDSCREENHEIGHT,    /* filled in later*/
  112.     2,    /* depth */
  113.     0, 0,    /* detail, block */
  114.     HIRES|LACE,CUSTOMSCREEN | NS_EXTENDED,
  115.     NULL,NULL,NULL,NULL
  116. };
  117.  
  118.  
  119. struct NewWindow newwindow =
  120. {
  121.     0, 0, 0, 0,                /* filled in later */
  122.     0, 0,
  123.     0,    /* filled in later */
  124.     0,    /* filled in later */
  125.     NULL, NULL, NULL, NULL, NULL,
  126.     0, 0, 0, 0, 0
  127. };
  128.  
  129. int font_w, font_h, baseline;    /* size of system default font */
  130. int titlefont_w, titlefont_h;    /* size of font used in the screen title (and menus) */
  131. int sys_white, sys_black, sys_medium, sys_bright;
  132. int screen_depth;
  133. int wb_width, wb_height;    /* size of workbench screen */
  134. int window_edge;            /* number of pixels to account for the window edge */
  135. int which_pal = 0, shift_key;
  136. int win2_row, win2_col;
  137.  
  138. UWORD *amy_cmap = 0L;
  139.  
  140. int menu_count[10] = {0,0,0,0,0,0,0,0,0,0};
  141. struct Menu *head_menu = 0L, *last_menu = 0L;
  142. int gadget_count = 0, gadget_height, gadget_spacing;
  143. struct Gadget *gadget_array[MAX_GADGETS];
  144.  
  145. /* these are for changing the values of toggleable menu items */
  146. struct MenuItem *mi_dtool, *mi_cross, *mi_coord;
  147.  
  148.  
  149. void open_stuff(depth, title)
  150. short depth;
  151. char *title;
  152. {
  153.   struct Screen wbdata;
  154.   struct RastPort temp_rp;    /* used to find font size */
  155.  
  156.   GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0);
  157.   IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0);
  158.  
  159.   if (!(ReqBase = (struct ReqLib *)OpenLibrary("req.library", 0L)))
  160.     sys_exit("Couldn't find the req library.  Is it in your libs: directory?");
  161.  
  162.   if (!(GetScreenData((char *)&wbdata, sizeof(struct Screen),
  163.     WBENCHSCREEN, NULL)))
  164.     sys_exit("unable to get screen info.");
  165.   wb_width = wbdata.ViewPort.DWidth;
  166.   wb_height = wbdata.ViewPort.DHeight;
  167.  
  168.   InitRastPort(&temp_rp);    /* find system font */
  169.   font_w = temp_rp.TxWidth;
  170.   font_h = temp_rp.TxHeight;
  171.   baseline = temp_rp.TxBaseline;
  172.   AskFont(&temp_rp, default_ta);
  173.   gadget_height = font_h + 2;
  174.  
  175.   newwindow.Flags =
  176.     WFLG_ACTIVATE |
  177.     WFLG_SMART_REFRESH |
  178.     WFLG_REPORTMOUSE |
  179.     WFLG_RMBTRAP;
  180.   newwindow.IDCMPFlags =
  181.     IDCMP_MOUSEBUTTONS |
  182.     IDCMP_VANILLAKEY |
  183.     IDCMP_MOUSEMOVE |
  184.     IDCMP_MENUPICK |
  185.     IDCMP_GADGETUP,
  186.   sys_medium = 0;
  187.   sys_bright = 3;
  188.  
  189.   if (flags.display_type & DF_WORKBENCH)
  190.     setup_for_workbench(&wbdata);
  191.   else
  192.     setup_for_custom_screen(depth, title);
  193.  
  194.   colors.point = sys_white;
  195.   colors.titleb = sys_black;
  196.   colors.face = colors.box = colors.titlea = sys_bright;
  197.   colors.erase = sys_black;
  198.  
  199.   newwindow.Width = sxmax;
  200.   newwindow.Height = symax;
  201.   newwindow.DetailPen = sys_white;
  202.   newwindow.BlockPen = sys_medium;
  203.   newwindow.Title = (UBYTE *)title;
  204.   edit_miny = titlefont_h + 4;
  205.   sxmax--;
  206.   symax--;
  207.   if (flags.display_type & DF_WORKBENCH)    /* allow for window border */
  208.   {
  209.     sxmax -= 4;
  210.     symax -= 2;
  211.   }
  212.   x_center = edit_minx + (sxmax - edit_minx)/2;
  213.   y_center = edit_miny + (symax - edit_miny)/2;
  214.  
  215.   if ((window = OpenWindow(&newwindow)) == NULL) sys_exit("no window");
  216.   rp = window->RPort;
  217.  
  218.   if (symax < 300)
  219.     gadget_spacing = font_h + 2;
  220.   else
  221.     gadget_spacing = font_h + 3;
  222.  
  223.   add_all_menus();
  224.   add_all_gadgets();
  225.  
  226.   myprocess = (struct Process *)FindTask((char *)0);
  227.   olderrorwindow = myprocess->pr_WindowPtr;
  228.   myprocess->pr_WindowPtr = (APTR)window;
  229. }
  230.  
  231.  
  232. void setup_for_workbench(wbdata)
  233. struct Screen *wbdata;
  234. {
  235.   unsigned short color1, color2;
  236.  
  237.   screen_rport = &(wbdata->RastPort);
  238.   screen_depth = wbdata->BitMap.Depth;
  239.   titlefont_h = wbdata->RastPort.TxHeight;
  240.   titlefont_w = wbdata->RastPort.TxWidth;
  241.   amy_cmap = (UWORD *)(wbdata->ViewPort.ColorMap->ColorTable);
  242.   sxmax = wb_width - 10;
  243.   symax = wb_height - 10;
  244.   newwindow.Screen = 0L;
  245.   newwindow.Type = WBENCHSCREEN;
  246.   newwindow.IDCMPFlags |= IDCMP_CLOSEWINDOW;
  247.   newwindow.Flags |= (WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_CLOSEGADGET);
  248.  
  249.   /* figure out the color scheme for this screen */
  250.   color1 = amy_cmap[1];
  251.   color2 = amy_cmap[2];
  252.   color1 = ((color1 & 0xf00) >> 8) + ((color1 & 0x0f0) >> 4) + (color1 & 0x00f);
  253.   color2 = ((color2 & 0xf00) >> 8) + ((color2 & 0x0f0) >> 4) + (color2 & 0x00f);
  254.   if (color1 > color2)
  255.   {
  256.     sys_white = 1;
  257.     sys_black = 2;
  258.   }
  259.   else
  260.   {
  261.     sys_white = 2;
  262.     sys_black = 1;
  263.   }
  264.   window_edge = 5;
  265. }
  266.  
  267.  
  268. void setup_for_custom_screen(depth, title)
  269. int depth;
  270. char *title;
  271. {
  272.   sys_white = 2;
  273.   sys_black = 1;
  274.  
  275.   NS.Width = wb_width;
  276.   NS.Depth = depth;
  277.   screen_depth = depth;
  278.  
  279.   NS.DetailPen = sys_black;
  280.   NS.BlockPen = sys_white;
  281.   if (flags.display_type & DF_MED_RES)
  282.       NS.ViewModes = HIRES;
  283.   else
  284.       NS.ViewModes = HIRES | LACE;
  285.  
  286.   mytags[0].ti_Tag = SA_Pens;
  287.   mytags[0].ti_Data = (ULONG) mypens;
  288.   mytags[1].ti_Tag = TAG_DONE;
  289.   mytags[1].ti_Data = NULL;
  290.   NS.Extension = mytags;
  291.   NS.DefaultTitle = (UBYTE *)title;
  292.  
  293.   screen = (struct Screen *) OpenScreen(&NS);
  294.   if (!screen) sys_exit("Can't open screen\n");
  295.  
  296.   screen_rport = &(screen->RastPort);
  297.   titlefont_h = screen_rport->TxHeight;
  298.   titlefont_w = screen_rport->TxWidth;
  299.  
  300.   vp = &(screen->ViewPort);
  301.   amy_cmap = (UWORD *)screen->ViewPort.ColorMap->ColorTable;
  302.   sxmax = screen->Width;
  303.   symax = screen->Height;
  304.  
  305.   if (!(flags.display_type & DF_SYS_PALETTE))
  306.       LoadRGB4(vp, palette[0], 1L<<depth);
  307.   newwindow.Screen = screen;
  308.   newwindow.Type = CUSTOMSCREEN;
  309.   newwindow.Flags |= (BORDERLESS | BACKDROP);
  310.  
  311.   window_edge = 1;
  312. }
  313.  
  314.  
  315. void sys_attach_menus()
  316. {
  317.   SetMenuStrip(window, head_menu);
  318. }
  319.  
  320.  
  321. void sys_refresh_gadgets()
  322. {
  323.   RefreshGadgets(window->FirstGadget, window, NULL);
  324. }
  325.  
  326.  
  327. void add_gadget(string, gflags)
  328. char *string;
  329. int gflags;
  330. {
  331.     int x, y, width;
  332.  
  333.     x = window_edge;
  334.     y = edit_miny + 1 + (gadget_count * gadget_spacing);
  335.     width = (GADX - 9) - window_edge;
  336.  
  337.     add_boolean_gadget(window, x, y, width, string, gflags, gadget_count + 1, 0);
  338.  
  339.     gadget_count++;
  340. }
  341.  
  342.  
  343. void add_boolean_gadget(wind, x, y, width, string, gflags, id, draw)
  344. struct Window *wind;
  345. int x, y, width;
  346. char *string;
  347. int gflags;
  348. int id;
  349. int draw;
  350. {
  351.   struct IntuiText *nt;
  352.   struct Gadget *ng;
  353.   int len = strlen(string), pix_width;
  354.   struct Border *border;
  355.   char *buf;
  356.  
  357.   if (id > MAX_GADGETS) return;
  358.  
  359.   nt = (struct IntuiText *)mem_alloc(sizeof(struct IntuiText));
  360.   ng = (struct Gadget *)mem_alloc(sizeof(struct Gadget));
  361.   buf = (char *)mem_alloc(len + 1);
  362.   strcpy(buf, string);
  363.  
  364.   pix_width = len * font_w;
  365.  
  366.   border = create_shadow_border(width, gadget_height, 1);
  367.  
  368.   nt->FrontPen = 1;
  369.   nt->BackPen = 0;
  370.   nt->DrawMode = JAM2;
  371.   nt->LeftEdge = (width - pix_width)/2;    /* centered text */
  372.   nt->TopEdge = 1;
  373.   if (flags.display_type & DF_WORKBENCH)
  374.     nt->ITextFont = default_ta;    /* default font */
  375.   else
  376.     nt->ITextFont = NULL;    /* default font */
  377.   nt->IText = buf;
  378.   nt->NextText = 0L;
  379.  
  380.   ng->NextGadget = 0L;
  381.   ng->LeftEdge = x;
  382.   ng->TopEdge = y;
  383.   ng->Width = width;
  384.   ng->Height = gadget_height;
  385.   ng->Activation = GACT_RELVERIFY | GACT_IMMEDIATE;
  386.   ng->GadgetType = GTYP_BOOLGADGET;
  387.   if (gflags & GF_NOSELECT)
  388.   {
  389.       ng->GadgetRender = (APTR)0;
  390.       ng->Flags = GFLG_GADGHNONE;    /* don't highlight */
  391.   }
  392.   else
  393.   {
  394.       ng->GadgetRender = (APTR)border;
  395.       ng->Flags = GFLG_GADGHCOMP;
  396.   }
  397.   ng->SelectRender = NULL;
  398.   ng->GadgetText = nt;
  399.   ng->MutualExclude = 0L;
  400.   ng->SpecialInfo = NULL;
  401.   ng->GadgetID = id;
  402.   ng->UserData = NULL;
  403.  
  404.   AddGadget(wind, ng, (UWORD)~0);    /* enforce append to list */
  405.   if (draw)                            /* draw this new (final) gadget */
  406.        RefreshGadgets(ng, wind, 0L);
  407.   gadget_array[id] = ng;
  408. }
  409.  
  410.  
  411. void add_long_gadget(wind, x, y, width, value, id, draw)
  412. struct Window *wind;
  413. int x, y;
  414. int width;
  415. long value;
  416. int id;
  417. int draw;
  418. {
  419.   struct Gadget *ng;
  420.   struct StringInfo *nsi;
  421.   struct Border *border;
  422.   char *buf;
  423.  
  424.   if (id > MAX_GADGETS) return;
  425.  
  426.   border = create_shadow_border(width, font_h, 0);
  427.  
  428.   ng = (struct Gadget *)mem_alloc(sizeof(struct Gadget));
  429.   nsi = (struct StringInfo *)mem_alloc(sizeof (struct StringInfo));
  430.   buf = (char *)mem_alloc(16);
  431.   sprintf(buf, "%ld", value);
  432.  
  433.   nsi->Buffer = buf;
  434.   nsi->UndoBuffer = NULL;
  435.   nsi->BufferPos = strlen(buf);
  436.   nsi->MaxChars = 16;
  437.   nsi->DispPos = 0;
  438.   nsi->Extension = NULL;
  439.   nsi->LongInt = value;
  440.   nsi->AltKeyMap = NULL;
  441.  
  442.   ng->NextGadget = 0L;
  443.   ng->LeftEdge = x;
  444.   ng->TopEdge = y;
  445.   ng->Width = width;
  446.   ng->Height = font_h;
  447.   ng->Activation = GACT_STRINGLEFT | GACT_LONGINT | GACT_RELVERIFY | GACT_IMMEDIATE;
  448.   ng->GadgetType = GTYP_STRGADGET;
  449.   ng->GadgetRender = (APTR)border;
  450.   ng->Flags = GFLG_GADGHCOMP;
  451.   ng->SelectRender = NULL;
  452.   ng->GadgetText = NULL;
  453.   ng->MutualExclude = 0L;
  454.   ng->SpecialInfo = nsi;
  455.   ng->GadgetID = id;
  456.   ng->UserData = NULL;
  457.  
  458.   AddGadget(wind, ng, (UWORD)~0);    /* enforce append to list */
  459.   if (draw)                            /* draw this new (final) gadget */
  460.        RefreshGadgets(ng, wind, 0L);
  461.   gadget_array[id] = ng;
  462. }
  463.  
  464.  
  465. /* create a "shadow" 3D box for use around a gadget */
  466.  
  467. struct Border *create_shadow_border(width, height, inside)
  468. int width, height;
  469. int inside;        /* if TRUE, put the border inside the gadget, else surrounding */
  470. {
  471.   struct Border *border_1, *border_2;
  472.   short *vectors_1, *vectors_2;
  473.   int x0, x1, y0, y1;
  474.  
  475.   border_1 = (struct Border *)mem_alloc(sizeof (struct Border));
  476.   border_2 = (struct Border *)mem_alloc(sizeof (struct Border));
  477.   vectors_1 = (short *)mem_alloc(6 * sizeof(short));
  478.   vectors_2 = (short *)mem_alloc(6 * sizeof(short));
  479.  
  480.   x0 = 0;
  481.   x1 = width-1;
  482.   y0 = 0;
  483.   y1 = height-1;
  484.   if (!inside)
  485.   {
  486.     x0--;
  487.     x1++;
  488.     y0--;
  489.     y1++;
  490.   }
  491.   vectors_1[0] = x0;
  492.   vectors_1[1] = y1;
  493.   vectors_1[2] = x0;
  494.   vectors_1[3] = y0;
  495.   vectors_1[4] = x1;
  496.   vectors_1[5] = y0;
  497.  
  498.   vectors_2[0] = x0+1;
  499.   vectors_2[1] = y1;
  500.   vectors_2[2] = x1;
  501.   vectors_2[3] = y1;
  502.   vectors_2[4] = x1;
  503.   vectors_2[5] = y0+1;
  504.  
  505.   border_1->LeftEdge = 0;
  506.   border_1->TopEdge = 0;
  507.   border_1->FrontPen = sys_white;
  508.   border_1->BackPen = 0;
  509.   border_1->DrawMode = JAM1;
  510.   border_1->Count = 3;
  511.   border_1->XY = vectors_1;
  512.   border_1->NextBorder = NULL;
  513.  
  514.   *border_2 = *border_1;
  515.   border_2->XY = vectors_2;
  516.   border_2->NextBorder = border_1;
  517.   border_2->FrontPen = sys_black;
  518.  
  519.   return border_2;
  520. }
  521.  
  522.  
  523. void add_menu(name)
  524. char *name;
  525. {
  526.   struct Menu *newmenu;
  527.   int len = strlen(name);
  528.   char *buf;
  529.  
  530.   newmenu = (struct Menu *)mem_alloc(sizeof(struct Menu));
  531.   buf = (char *)mem_alloc(len + 1);
  532.   strcpy(buf, name);
  533.  
  534.   newmenu->NextMenu = 0L;
  535.   newmenu->LeftEdge = 0;
  536.   newmenu->TopEdge = 0;
  537.   newmenu->Width = len * titlefont_w + 8;
  538.   newmenu->Height = titlefont_h;
  539.   newmenu->Flags = MENUENABLED;
  540.   newmenu->MenuName = buf;
  541.   newmenu->FirstItem = 0L;
  542.  
  543.   /* add to linked list */
  544.   if (!head_menu)
  545.   {
  546.     newmenu->LeftEdge = 0L;
  547.     head_menu = newmenu;
  548.   }
  549.   else
  550.   {
  551.     newmenu->LeftEdge = last_menu->LeftEdge + last_menu->Width + 6;
  552.     last_menu->NextMenu = newmenu;
  553.   }
  554.   last_menu = newmenu;
  555. }
  556.  
  557.  
  558. struct MenuItem *add_menu_item(menu_num, name, mflags, shortcut)
  559. char *name;
  560. int menu_num, mflags;
  561. char shortcut;
  562. {
  563.   struct IntuiText *newtext;
  564.   struct MenuItem *newitem, *lastitem;
  565.   struct Menu *menu;
  566.   int len = strlen(name), mcount;
  567.   char *buf;
  568.  
  569.   /* find the menu we're going to attach this item to */
  570.   menu = head_menu;
  571.   for (mcount = 0; mcount < menu_num; mcount++) menu = menu->NextMenu;
  572.  
  573.   newtext = (struct IntuiText *)mem_alloc(sizeof(struct IntuiText));
  574.   newitem = (struct MenuItem *)mem_alloc(sizeof(struct MenuItem));
  575.   buf = (char *)mem_alloc(strlen(name) + 1);
  576.   strcpy(buf, name);
  577.  
  578.   newtext->FrontPen = 2;
  579.   newtext->BackPen = 1;
  580.   newtext->DrawMode = JAM1;
  581.   newtext->LeftEdge = 0;
  582.   newtext->TopEdge = 0;
  583.   if (flags.display_type & DF_WORKBENCH)
  584.     newtext->ITextFont = default_ta;    /* default font */
  585.   else
  586.     newtext->ITextFont = NULL;    /* default font */
  587.   newtext->IText = buf;
  588.   newtext->NextText = 0L;
  589.  
  590.   newitem->NextItem = 0L;
  591.   newitem->LeftEdge = 0;
  592.   newitem->TopEdge = menu_count[menu_num] * (font_h + 1);
  593.   newitem->Width = len * font_w + 4;
  594.   newitem->Height = font_h + 1;
  595.   newitem->Flags = ITEMTEXT+HIGHCOMP;
  596.   newitem->MutualExclude = 0;
  597.   newitem->ItemFill = (APTR)newtext;
  598.   newitem->SelectFill = 0L;
  599.   newitem->Command = shortcut;
  600.   newitem->SubItem = 0L;
  601.   newitem->NextSelect = 0L;
  602.  
  603.   if (!(mflags & MO_NOTENABLED))
  604.     newitem->Flags |= ITEMENABLED;
  605.   if (mflags & MO_TOGGLE)
  606.   {
  607.     newitem->Flags |= (CHECKIT | MENUTOGGLE);
  608.     newitem->Width += CHECKWIDTH + 1;
  609.     newtext->LeftEdge += CHECKWIDTH + 1;
  610.     if (mflags & MO_CHECKED)
  611.       newitem->Flags |= CHECKED;
  612.   }
  613.  
  614.   if (shortcut)
  615.   {
  616.     newitem->Flags |= COMMSEQ;
  617.     newitem->Width += 40;
  618.   }
  619.  
  620.   menu->Height += (titlefont_h + 1);
  621.  
  622.   /* add to linked list */
  623.   lastitem = menu->FirstItem;
  624.   if (!lastitem)
  625.   {
  626.     menu->FirstItem = newitem;    /* first item */
  627.   }
  628.   else        /* find the first item */
  629.   {
  630.     while (lastitem->NextItem) lastitem = lastitem->NextItem;
  631.     lastitem->NextItem = newitem;
  632.   }
  633.  
  634.   menu_count[menu_num]++;    /* one more item for this menu */
  635.   return newitem;
  636. }
  637.  
  638.  
  639. void toggle_menuitem(which_menu, which_item)
  640. int which_menu, which_item;
  641. {
  642.     struct Menu *m;
  643.     struct MenuItem *mi;
  644.     int i1;
  645.  
  646.     m = head_menu;
  647.     for (i1 = 0; i1 < which_menu; i1++) m = m->NextMenu;
  648.     mi = m->FirstItem;
  649.     for (i1 = 0; i1 < which_item; i1++) mi = mi->NextItem;
  650.  
  651.     mi->Flags ^= CHECKED;
  652. }
  653.  
  654.  
  655. void sys_exit(s)
  656. char *s;
  657. {
  658.   unsigned short i;
  659.   for (i = 0; i < polys; i++) kill_poly(i);
  660.   free_arrays();
  661.  
  662.   if (myprocess) myprocess->pr_WindowPtr = olderrorwindow;
  663.   if (window)
  664.   {
  665.     ClearMenuStrip(window);
  666.     CloseWindow(window);
  667.   }
  668.   clear_remember(0);
  669.   if (screen) CloseScreen(screen);
  670.   if (ReqBase)
  671.   {
  672.     PurgeFiles(&MyFileReqStruct);    /* Only necessary if the FRQCACHINGM flag */
  673.                                     /* is set in the file requester structure. */
  674.     CloseLibrary(ReqBase);
  675.   }
  676.   if (GfxBase) CloseLibrary(GfxBase);
  677.   if (IntuitionBase) CloseLibrary(IntuitionBase);
  678.   if (*s) puts(s);
  679.   exit (0);
  680. }
  681.  
  682.  
  683. void enable_menus(on)
  684. char on;
  685. {
  686.   if (on) window->Flags &= ~RMBTRAP;
  687.      else window->Flags |= RMBTRAP;
  688. }
  689.  
  690.  
  691. void wait_for_message()
  692. {
  693.   Wait(1L<<window->UserPort->mp_SigBit);
  694. }
  695.  
  696.  
  697. long last_secs = 0, last_micros = 0;    /* Time of last button click */
  698. short last_x, last_y;                    /* pointer xy at time of last click */
  699.  
  700. void handle_messages()
  701. {
  702.     ULONG class;
  703.     USHORT code, qual, mflag = 0;
  704.     struct Gadget *gadget;
  705.     long secs, micros;
  706.     coord newx, newy;
  707.     struct IntuiMessage *message;
  708.  
  709.     newx = window->MouseX;
  710.     newy = window->MouseY;
  711.  
  712.     while (message = (struct IntuiMessage *)GetMsg(window->UserPort))
  713.     {
  714.         newx = message->MouseX;
  715.         newy = message->MouseY;
  716.         class = message->Class;
  717.         if (class == IDCMP_MOUSEMOVE)    /* quickly handle mousemoves */
  718.         {
  719.           mflag = 1;
  720.           ReplyMsg(message);
  721.           continue;
  722.         }
  723.         code = message->Code;
  724.         qual = message->Qualifier;
  725.         gadget = (struct Gadget *)(message->IAddress);
  726.         secs = message->Seconds;
  727.         micros = message->Micros;
  728.         ReplyMsg(message);
  729.  
  730.         switch (class)
  731.         {
  732.             case IDCMP_MOUSEBUTTONS:
  733.               switch(code)
  734.               {
  735.                 case SELECTDOWN:
  736.                 case MENUDOWN:
  737.                   if (qual & (IEQUALIFIER_LSHIFT | IEQUALIFIER_LSHIFT))
  738.                     shift_key = 1;    /* shift key down */
  739.                   else
  740.                     shift_key = 0;    /* shift key up */
  741.  
  742.                   if (my > edit_miny && mx > edit_minx)    /* in the editing area */
  743.                   {
  744.                     code = (code == MENUDOWN ? 1 : 0);
  745.                     if (mode == M_DIST || mode == M_SELE || mode == M_MOVP)
  746.                     {
  747.                       if (DoubleClick(last_secs, last_micros, secs, micros)
  748.                             && abs(last_x - mx) < 5 && abs(last_y - my) < 5)
  749.                         code |= MF_DOUBLE;
  750.                     }
  751.                     if (shift_key) code |= MF_SHIFTED;
  752.                     mouse_down(code);
  753.                     last_secs = secs;
  754.                     last_micros = micros;
  755.                     last_x = mx;
  756.                     last_y = my;
  757.                   }
  758.                   break;
  759.                 case SELECTUP:
  760.                 case MENUUP: mouse_up(); break;
  761.               }
  762.               break;
  763.             case IDCMP_VANILLAKEY:
  764.               switch (code)
  765.               {
  766.                 case '`':
  767.                     which_pal++;
  768.                     if (which_pal == PALETTES) which_pal = 0;
  769.                     LoadRGB4(vp, palette[which_pal], 4);
  770.                     break;
  771.                 default:
  772.                     handle_key(code); break;
  773.               }
  774.               break;
  775.             case IDCMP_MENUPICK:    sys_handle_menu(code); break;
  776.             case IDCMP_GADGETUP:    handle_gadget(gadget->GadgetID); break;
  777.             case IDCMP_CLOSEWINDOW:    sys_exit(""); break;
  778.         }
  779.     }
  780.     if (mflag) update_movement(newx, newy);
  781. }
  782.  
  783.  
  784. void sys_handle_menu(menu_number)
  785. unsigned short menu_number;
  786. {
  787.   struct MenuItem *mi;
  788.  
  789.   while (menu_number != MENUNULL)
  790.   {
  791.     mi = ItemAddress(head_menu, (long)menu_number);
  792.     handle_menu(MENUNUM(menu_number), ITEMNUM(menu_number), ((mi->Flags & CHECKED) > 0));
  793.     menu_number = mi->NextSelect;
  794.   }
  795. }
  796.  
  797.  
  798. void *sys_alloc(size)
  799. unsigned int size;
  800. {
  801.   return (void *)AllocMem((long)size, 0L);
  802. }
  803.  
  804.  
  805. void sys_free(ptr, size)
  806. void *ptr;
  807. unsigned int size;
  808. {
  809.   FreeMem(ptr, (long)size);
  810. }
  811.  
  812.  
  813. char *sys_file_requestor(title, showpattern)
  814. char *title;
  815. char *showpattern;        /* show only files matching this pattern */
  816. {
  817.   answerarray[0] = 0;
  818.  
  819.   /* Initialize the 'PathName' field so that the file requester will */
  820.   /* construct a complete path name for me.  It will also put the two */
  821.   /* parts of the answer (directory and file name) into the directory */
  822.   /* file name which I also decided to supply it with.  Since the */
  823.   /* directory and file name arrays are present, it will use their */
  824.   /* initial contents as the initial file and directory.  If they aren't */
  825.   /* present it will leave both blank to start. */
  826.  
  827.   MyFileReqStruct.PathName = answerarray;
  828.   MyFileReqStruct.Dir = directoryname;
  829.   MyFileReqStruct.File = filename;
  830.   MyFileReqStruct.Title = title;
  831.  
  832.   /* The directory caching of this file requester is one of its nice */
  833.   /* features, so I decided to show it off.  It is completely optional */
  834.   /* though, so if you don't want it, don't set this flag.  If you do */
  835.   /* want it, don't forget to call PurgeFiles() when you are done. */
  836.  
  837.   MyFileReqStruct.Flags = FRQCACHINGM;
  838.  
  839.   /* Initialize a few colour fields.  Not strictly necessary, but */
  840.   /* personally, I like having my files a different colour from my */
  841.   /* directories. */
  842.  
  843.   MyFileReqStruct.dirnamescolor = 2;
  844.   MyFileReqStruct.devicenamescolor = 2;
  845.   MyFileReqStruct.numlines = 35;
  846.  
  847.   strcpy(MyFileReqStruct.Show, showpattern);
  848.  
  849.   /* I could also make it larger, pass it a file and/or directory */
  850.   /* name, set various flags and customize */
  851.   /* in many other ways, but I wanted to show that it can be easily */
  852.   /* used without having to fill in a lot of fields. */
  853.  
  854.   if (FileRequester(&MyFileReqStruct))
  855.     return answerarray;
  856.   else
  857.     return (char *)0;
  858. }
  859.  
  860.  
  861. void sys_window(cols, rows, title)
  862. int cols, rows;
  863. char *title;
  864. {
  865.   int width, height;
  866.  
  867.   width = cols * font_w + 8;
  868.   height = rows * (font_h+3) + titlefont_h + 6 + 2;
  869.  
  870.   newwindow.Flags =
  871.     WFLG_ACTIVATE |
  872.     WFLG_DRAGBAR |
  873.     WFLG_CLOSEGADGET |
  874.     WFLG_SMART_REFRESH |
  875.     WFLG_RMBTRAP;        /* we won't have menus */
  876.   newwindow.IDCMPFlags =
  877.     IDCMP_GADGETDOWN |
  878.     IDCMP_MOUSEBUTTONS |
  879.     IDCMP_CLOSEWINDOW |
  880.     IDCMP_GADGETUP;        /* we're only interested in gadgets */
  881.  
  882.   newwindow.Width = width;
  883.   newwindow.Height = height;
  884.   newwindow.LeftEdge = (sxmax - width) / 2;    /* centered on the screen */
  885.   newwindow.TopEdge = (symax - height) / 2;
  886.   newwindow.DetailPen = sys_medium;    /* These are only used under 1.3 */
  887.   newwindow.BlockPen = sys_black;
  888.   newwindow.Title = title;
  889.  
  890.   if ((window2 = OpenWindow(&newwindow)) == NULL)
  891.     sys_exit("unable to open second window");
  892.   rp2 = window2->RPort;
  893.   active_text = 0;
  894.  
  895.   win2_mempoint = members;
  896. }
  897.  
  898.  
  899. void sys_close_window()
  900. {
  901.     if (window2)
  902.     {
  903.         CloseWindow(window2);
  904.         window2 = NULL;
  905.         rp2 = NULL;
  906.         clear_remember(win2_mempoint);
  907.     }
  908. }
  909.  
  910.  
  911. void sys_say_text(str)
  912. char *str;
  913. {
  914.     int x, y;
  915.     int len = strlen(str);
  916.  
  917.     if (!window2) return;
  918.     x = 6+(win2_col * font_w);
  919.     y = titlefont_h + 6 + (win2_row*(font_h+3)) + baseline;
  920.     Move(rp2, x, y);
  921.     SetAPen(rp2, sys_black);
  922.     Text(rp2, str, len);
  923.     win2_col += len;    /* advance the cursor */
  924. }
  925.  
  926.  
  927. void sys_get_long(value, id)
  928. long value;
  929. int id;
  930. {
  931.     int x, y, width;
  932.  
  933.     if (!window2) return;
  934.     win2_col++;
  935.     x = 6+(win2_col * font_w);
  936.     y = titlefont_h + 6 + (win2_row*(font_h+3));
  937.     width = 8 * font_w;
  938.  
  939.     add_long_gadget(window2, x, y, width, value, id, 1);
  940. }
  941.  
  942.  
  943. void sys_boolean(string, id)
  944. char *string;
  945. int id;
  946. {
  947.     int x, y, len, width;
  948.  
  949.     if (!window2) return;
  950.     x = 6+(win2_col * font_w);
  951.     y = titlefont_h + 6 + (win2_row*(font_h+3));
  952.     len = strlen(string);
  953.     width = len * font_w + 6;    /* a few pixels on each side */
  954.  
  955.     add_boolean_gadget(window2, x-3, y, width, string, 0, id, 1);
  956.     win2_col += (len + 1);
  957. }
  958.  
  959.  
  960. void sys_activate(id)
  961. int id;
  962. {
  963.     int success;
  964.  
  965.     success = ActivateGadget(gadget_array[id], window2, 0L);
  966.     if (success) active_text = id;
  967. }
  968.  
  969.  
  970. void sys_movecur(col, row)
  971. int col, row;
  972. {
  973.     win2_row = row;
  974.     win2_col = col;
  975. }
  976.  
  977.  
  978. int sys_read_event(id, data)
  979. int *id;
  980. long *data;
  981. {
  982.     ULONG class;
  983.     USHORT code;
  984.     struct Gadget *gadget;
  985.     struct IntuiMessage *message;
  986.     struct StringInfo *si;
  987.     int prev_active_text;
  988.  
  989.     while (1)
  990.     {
  991.         Wait(1L<<window2->UserPort->mp_SigBit);
  992.  
  993.         message = (struct IntuiMessage *)GetMsg(window2->UserPort);
  994.         class = message->Class;
  995.         code = message->Code;
  996.         gadget = (struct Gadget *)(message->IAddress);
  997.         ReplyMsg(message);
  998.  
  999.         prev_active_text = active_text;
  1000.         switch (class)
  1001.         {
  1002.             case IDCMP_MOUSEBUTTONS:    /* we have to let the application know */
  1003.                 if (active_text)
  1004.                     sys_activate(active_text);
  1005.             case IDCMP_GADGETDOWN:    /* If the user presses on another gadget */
  1006.                 if (active_text)
  1007.                 {
  1008.                     *id = active_text;
  1009.                     si = (struct StringInfo *)(gadget_array[active_text]->SpecialInfo);
  1010.                     *data = si->LongInt;
  1011.                 }
  1012.                 if (class == IDCMP_GADGETDOWN)
  1013.                 {
  1014.                     if (gadget->GadgetType == GTYP_STRGADGET)
  1015.                         active_text = gadget->GadgetID;
  1016.                 }
  1017.                 if (prev_active_text) return EV_CHECKINT;
  1018.                 break;
  1019.             case IDCMP_GADGETUP:
  1020.                 active_text = 0;
  1021.                 if (gadget->GadgetType == GTYP_BOOLGADGET)
  1022.                 {
  1023.                     *id = gadget->GadgetID;
  1024.                     *data = ((gadget->Flags & GFLG_SELECTED) > 0);
  1025.                     return EV_HITBUTTON;
  1026.                 }
  1027.                 else
  1028.                 {
  1029.                     *id = gadget->GadgetID;
  1030.                     si = (struct StringInfo *)(gadget->SpecialInfo);
  1031.                     *data = si->LongInt;
  1032.                     return EV_HITRETURN;
  1033.                 }
  1034.             case IDCMP_CLOSEWINDOW:
  1035.                 return EV_CANCEL;
  1036.         }
  1037.     }
  1038. }
  1039.  
  1040.  
  1041. /* remember where we allocated memory, so that we can free
  1042.     it easily later */
  1043.  
  1044. void *mem_alloc(bytes)
  1045. long bytes;
  1046. {
  1047.     void *vapor;    /* Vat a vapid vapor pointer! */
  1048.  
  1049.     vapor = (void *)AllocMem(bytes, 0L);
  1050.  
  1051.     remember_mem[members].memory = vapor;
  1052.     remember_mem[members].bytes = bytes;
  1053.     members++;
  1054.     return vapor;
  1055. }
  1056.  
  1057.  
  1058. void clear_remember(to_where)
  1059. int to_where;
  1060. {
  1061.     int mem;
  1062.  
  1063.     for (mem = to_where; mem < members; mem++)
  1064.         FreeMem(remember_mem[mem].memory, remember_mem[mem].bytes);
  1065.     members = to_where;
  1066. }
  1067.  
  1068.